package com.motu.vertx.module.utility.model;

import com.motu.vertx.module.utility.base.BaseServerParam;
import com.motu.vertx.module.utility.base.ServerConfig;
import com.motu.vertx.module.utility.mysql.MysqlClient;
import com.motu.vertx.module.utility.mysql.MysqlTool;
import com.motu.vertx.module.utility.redis.RedisTools;
import com.motu.vertx.module.utility.toolset.TimeUtils;
import com.motu.vertx.module.utility.toolset.Tool;
import io.vertx.core.*;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.sqlclient.Pool;
import io.vertx.redis.client.RedisAPI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.Map.Entry;

public class EntityManager {
    public final static Logger logger = LoggerFactory.getLogger(EntityManager.class);

    public static final long lock_timeout = 3000;// 单次锁超时时间（单位毫秒）
    public static final int lock_expire = 5;// 锁过期时间（单位秒）
    public static final int lock_sleep = 10;// 锁请求休眠时间（单位毫秒）

    public static final String ALL_LIST_KEY = "-1";// 全表列表关键字

    /**
     * 是否是新规范代码
     */
    public static boolean isNewCode() {
        return true;
    }

//    public static RedisAPI getRedisClient() {
//        return redisClient;
//    }

    // redis不存在时是否读取数据库
    private static boolean isLoadDB() {
        return BaseServerParam.REDIS_EXPIRE_TIME > 0;
    }

    /**
     * 获取用户延迟入库列表key
     */
    public static String getUserUpdateDbListKey(long userId) {
        return "list.updatedb.user." + userId;
    }

    /***
     * 获取更新数据库key
     */
    public static final String getUpdateDbKey() {
        return "vdb.list";
    }

    public static String getKey(String entityKey, Object... values) {
        String key = entityKey;
        for (int i = 0; i < values.length; i++) {
            key += "." + values[i];
        }
        return key;
    }

    public static String getValue(Object... values) {
        String value = "";
        for (int i = 0; i < values.length; i++) {
            if (value.equals("")) {
                value = String.valueOf(values[i]);
            } else {
                value += "." + values[i];
            }
        }
        return value;
    }

    public static String getListKey(String entityKey, String listKeyField, String listKeyId) {
        if (listKeyField.equals(ALL_LIST_KEY)) {
            return entityKey;
        } else {
            return getKey(entityKey, listKeyId);
        }
    }

    public static String getEntityInitKey(String entityKey) {
        return "entity.init." + entityKey;
    }

    /**
     * 获取额外的排序列表key
     * @param listKey
     */
    public static String getOrderListKey(String listKey) {
        return "list." + listKey;
    }

    public static String getEntityKey(Class cls, Object... values) {
        String redisKey = isNewCode() ? cls.getSimpleName() : cls.getSimpleName().toLowerCase();// 新规范类名，旧规范表名
        String key= getKey(redisKey, values);
        return key;
    }

    // 根据ID获取实体类，不存在返回null
    @SuppressWarnings({"rawtypes"})
    public static Model getEntity(Class cls, long id) {
        return loadEntity(cls, false, id);
    }

    // 根据ID获取实体类，不存在返回null（不执行reset方法）
    @SuppressWarnings({"rawtypes"})
    public static Model getEntityNotReset(Class cls, long id) {
        Object[] values = {id};
        return loadEntity(cls, false,false, values);
    }

    // 根据两个关键字获取实体类，不存在返回null
    @SuppressWarnings({"rawtypes"})
    public static Model getEntity(Class cls, long value1, long value2) {
        if (value1 == 0 && value2 == 0) {
            logger.warn("getEntity error cls:" + cls.getName() + " value1:" + value1 + " value2:" + value2);
            return null;
        }
        return loadEntity(cls, false, value1, value2);
    }

    // 根据多个关键字获取实体类，不存在返回null
    @SuppressWarnings({"rawtypes"})
    public static Model getEntity(Class cls, Object... values) {
        return loadEntity(cls, false, values);
    }

    @SuppressWarnings({"rawtypes"})
    public static Model getUniqueEntity(Class cls, long id, boolean noExistInsert) {
        return loadEntity(cls, noExistInsert, id);
    }

    // 根据ID获取唯一实体类，不存在会新增数据
    @SuppressWarnings({"rawtypes"})
    public static Model getUniqueEntity(Class cls, long id) {
        return loadEntity(cls, true, id);
    }

    // 根据ID获取唯一实体类，不存在会新增数据（不执行reset方法）
    @SuppressWarnings({"rawtypes"})
    public static Model getUniqueEntityNotReset(Class cls, long id) {
        Object[] values = {id};
        return loadEntity(cls, false,true, values);
    }

    // 根据关键字获取列表信息
    @SuppressWarnings({"rawtypes"})
    public static List<Model> getEntityList(Class cls, long listKeyId) {
        return loadEntityList(cls, String.valueOf(listKeyId));
    }

    // 根据关键字和id数组获取列表信息
    @SuppressWarnings({"rawtypes"})
    public static List<Model> getEntityList(Class cls, long listKeyId, JsonArray idArray) {
        return loadEntityList(cls, String.valueOf(listKeyId), idArray);
    }

    // 根据关键字获取列表信息
    @SuppressWarnings({"rawtypes"})
    public static List<Model> getEntityList(Class cls, String listKeyId) {
        return loadEntityList(cls, listKeyId);
    }

    // 根据关键字和id数组获取列表信息
    @SuppressWarnings({"rawtypes"})
    public static List<Model> getEntityList(Class cls, String listKeyId, JsonArray idArray) {
        return loadEntityList(cls, listKeyId, idArray);
    }

    // 获取全部列表信息
    @SuppressWarnings({"rawtypes"})
    public static List<Model> getEntityList(Class cls) {
        return loadEntityList(cls, null);
    }

    // 根据id数组获取列表信息
    @SuppressWarnings({"rawtypes"})
    public static List<Model> getEntityList(Class cls, JsonArray idArray) {
        return loadEntityList(cls, null, idArray);
    }

    // 获取列表数量
    @SuppressWarnings({"rawtypes"})
    public static long getEntityCount(Class cls, long listKeyId) {
        return getEntityCount(cls, String.valueOf(listKeyId));
    }

    // 获取列表数量
    @SuppressWarnings({"rawtypes"})
    public static long getEntityCount(Class cls, String listKeyId) {
        String entityKey = isNewCode() ? cls.getSimpleName() : cls.getSimpleName().toLowerCase();// 新规范类名，旧规范表名
        String listKeyField = getListKeyField(cls);
        String listKey = getListKey(entityKey, listKeyField, listKeyId);

        // 列表数据如果过期从数据库加载
        boolean exist = EntityManager.listExpireLoadFromDB(cls, listKeyField, listKey);
        if (!exist) {
            return 0;
        }

        long count = Future.await(RedisTools.getHashLen( listKey));
        return count;
    }

    //  获取列表所有key
    @SuppressWarnings({"rawtypes"})
    public static JsonArray getEntityKeyList(Class cls, long listKeyId) {
        return getEntityKeyList(cls, String.valueOf(listKeyId));
    }

    // 获取列表所有key
    @SuppressWarnings({"rawtypes"})
    public static JsonArray getEntityKeyList(Class cls, String listKeyId) {
        String entityKey = isNewCode() ? cls.getSimpleName() : cls.getSimpleName().toLowerCase();// 新规范类名，旧规范表名
        String listKeyField = getListKeyField(cls);
        String listKey = getListKey(entityKey, listKeyField, listKeyId);

        // 列表数据如果过期从数据库加载
        boolean exist = EntityManager.listExpireLoadFromDB(cls, listKeyField, listKey);
        if (!exist) {
            return new JsonArray();
        }

        JsonArray result = Future.await(RedisTools.getHashKeys( listKey));
        return result;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    public static JsonObject getEntityObject(Class cls, Object... values) {
        return loadJsonObject(cls, false, values);
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private static Model loadEntity(Class cls, boolean noExistInsert, Object... values) {
        return loadEntity(cls, true, noExistInsert, values);// 默认需要执行reset方法
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private static Model loadEntity(Class cls, boolean reset, boolean noExistInsert, Object... values) {
        JsonObject result = loadJsonObject(cls, noExistInsert, values);

        // json对象转实体类
        Model entity = null;
        if (isEntityNotNull(result)) {
            entity = (Model) result.mapTo(cls);
        }

        // 调用reset方法
        if (entity != null && reset) {
            entity.reset();
        }

        return entity;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private static JsonObject loadJsonObject(Class cls, boolean noExistInsert, Object... values) {
        String entityKey = isNewCode() ? cls.getSimpleName() : cls.getSimpleName().toLowerCase();// 新规范类名，旧规范表名
        String tableName = isNewCode() ? Tool.upperCaseToUnderline(entityKey) : entityKey;// 表名
        String listKeyField = getListKeyField(cls);// 获取列表关键字段
        JsonObject result = null;

        // 单条数据
        if (Tool.isEmpty(listKeyField)) {
            // 单条数据的传参只能有1个值，就是dbid
            if (values.length != 1) {
                logger.error("loadEntity error get one data values != 1 class name = {}", cls.getSimpleName());
                return null;
            }

            String key = getKey(entityKey, values[0]);
            result = Future.await(RedisTools.getHashJsonObject( key));

            // 数据不存在从数据库加载
            if (!isEntityNotNull(result)) {
                result = loadEntityFromDB(cls, tableName, key, noExistInsert, values);
            }

            // 设置读取对象的过期时间
            if (isEntityNotNull(result)) {
                setEntityExpireTime(key, cls, result);
            }
        }

        // 列表数据
        else {
            // 不是全表数据的列表数据的传参必须>=2，第一个是列表的关键值
            if (!listKeyField.equals(ALL_LIST_KEY) && values.length < 2) {
                logger.error("loadEntity error get list data values < 2 class name = {}", cls.getSimpleName());
                return null;
            }

            String listKeyId = String.valueOf(values[0]);// 不是全表数据才有用
            String listKey = getListKey(entityKey, listKeyField, listKeyId);
            String listItemKey = getListItemKey(values);

            // 判断列表是否存在
            boolean exists = Future.await(RedisTools.exists( listKey));
            if (exists) {
                // 列表数据存在，则从缓存中获取
                String item = Future.await(RedisTools.getHashField( listKey, listItemKey));
                if (!Tool.isEmpty(item)) {
                    result = new JsonObject(item);
                }
            } else {
                // 不存在从数据库读取列表
                int updateDbType = getUpdateDbType(cls);// 更新数据库类型
                if (updateDbType != BaseModel.UPDATE_DB_TYPE_NOT) {
                    JsonObject list = loadListFromDB(cls, tableName, listKeyField, listKey, listKeyId);
                    if (list != null && list.containsKey(listItemKey)) {
                        result = list.getJsonObject(listItemKey);
                    }
                }
            }
        }

       return result;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private static List<Model> loadEntityList(Class cls, String listKeyId) {
        return loadEntityList(cls, listKeyId, null);
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private static List<Model> loadEntityList(Class cls, String listKeyId, JsonArray idArray) {
        String entityKey = isNewCode() ? cls.getSimpleName() : cls.getSimpleName().toLowerCase();// 新规范类名，旧规范表名
        String tableName = isNewCode() ? Tool.upperCaseToUnderline(entityKey) : entityKey;
        String listKeyField = getListKeyField(cls);
        String listKey = getListKey(entityKey, listKeyField, listKeyId);
        boolean isOrderList = isOrderList(cls);

        // 判断列表是否存在
        JsonObject result = null;
        boolean exists = Future.await(RedisTools.exists( listKey));
        if (exists) {
            if (idArray != null){
                // 根据listKey和idArray获取
                result = Future.await(RedisTools.getHashJsonObject( listKey, idArray));
            } else{
                // 获取listKey获取
                result = Future.await(RedisTools.getHashJsonObject( listKey));
            }
        } else {
            // 不存在从数据库读取列表
            int updateDbType = getUpdateDbType(cls);// 更新数据库类型
            if (updateDbType != BaseModel.UPDATE_DB_TYPE_NOT) {
                result = loadListFromDB(cls, tableName, listKeyField, listKey, listKeyId);
                // 如果有传idArray，则需要根据idArray过滤数据
                if (idArray != null && result != null && result.size() > 0){
                    JsonObject result2 = new JsonObject();
                    for (int i = 0; i < idArray.size(); i++) {
                        String key = String.valueOf(idArray.getValue(i));
                        if (result.containsKey(key)){
                            result2.put(key, result.getValue(key));
                        }
                    }
                    result = result2;
                }
            }
        }

        List<Model> list = new ArrayList<Model>();
        if (result == null) {
            return list;
        }

        // 创建实体类列表
        for (Iterator<Entry<String, Object>> iter = result.iterator(); iter.hasNext(); ) {
            Entry<String, Object> entry = iter.next();
            Object value = entry.getValue();
            JsonObject jsonObject = null;
            if (value instanceof String){
                jsonObject = new JsonObject((String) entry.getValue());
            } else if (value instanceof JsonObject){
                jsonObject = (JsonObject)value;
            }
            if (jsonObject != null){
                Model entity = (Model) jsonObject.mapTo(cls);
                entity.reset();
                list.add(entity);
            }
        }

        // 有序列表默认按ID升序
        if (isOrderList && list.size() > 1){
            Collections.sort(list, Comparator.comparing((Model o) -> o.getId()));
        }

        // 每次获取列表时都重新设置一下过期时间
        int expireTime = setRedisExpireTime(listKey, cls);
        if (isOrderList){
            setRedisExpireTime(EntityManager.getOrderListKey(listKey), expireTime);
        }

        return list;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    public static JsonArray getEntityArray(Class cls, long listKeyId) {
        return loadJsonArray(cls, String.valueOf(listKeyId));
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    public static JsonArray getEntityArray(Class cls, String listKeyId) {
        return loadJsonArray(cls, listKeyId);
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private static JsonArray loadJsonArray(Class cls, String listKeyId) {
        String entityKey = isNewCode() ? cls.getSimpleName() : cls.getSimpleName().toLowerCase();// 新规范类名，旧规范表名
        String tableName = isNewCode() ? Tool.upperCaseToUnderline(entityKey) : entityKey;
        String listKeyField = getListKeyField(cls);
        String listKey = getListKey(entityKey, listKeyField, listKeyId);
        boolean isOrderList = isOrderList(cls);

        // 判断列表是否存在
        JsonObject result = null;
        boolean exists = Future.await(RedisTools.exists( listKey));
        if (exists) {
            result = Future.await(RedisTools.getHashJsonObject( listKey));
        } else {
            // 不存在从数据库读取列表
            int updateDbType = getUpdateDbType(cls);// 更新数据库类型
            if (updateDbType != BaseModel.UPDATE_DB_TYPE_NOT) {
                result = loadListFromDB(cls, tableName, listKeyField, listKey, listKeyId);
            }
        }

        JsonArray jsonArray = new JsonArray();
        if (result == null) {
            return jsonArray;
        }

        // 创建列表
        for (Iterator<Entry<String, Object>> iter = result.iterator(); iter.hasNext(); ) {
            Entry<String, Object> entry = iter.next();
            JsonObject jsonObject = new JsonObject((String) entry.getValue());
            jsonArray.add(jsonObject);
        }

        // 有序列表默认按ID升序
        if (isOrderList && jsonArray.size() > 1){
            Collections.sort(jsonArray.getList(), Comparator.comparing((JsonObject o) -> o.getInteger("id")));
        }

        return jsonArray;
    }

    @SuppressWarnings("rawtypes")
    private static JsonObject loadEntityFromDB(Class cls, String tableName, String key, boolean noExistInsert, Object... values) {
        // 获取更新数据库类型
        int updateDbType = getUpdateDbType(cls);

        // 获取id
        long id = Long.parseLong(String.valueOf(values[0]));

        // 是否需要从数据库加载
        if (EntityManager.isLoadDB() && updateDbType != BaseModel.UPDATE_DB_TYPE_NOT) {

            // 先判断数据有没有初始化过
            boolean entityInit = Future.await(RedisTools.exists( getEntityInitKey(key)));

            // 有初始化过才需要从数据库读取
            if (entityInit) {
                // 单条数据根据id查询
                String sql = "SELECT * FROM " + tableName + " where id = ?;";
                JsonArray sqlParams = new JsonArray();
                sqlParams.add(id);

                logger.info("loadEntityFromDB sql = {} sqlParams = {}", sql, sqlParams);

                JsonObject jsonObject = Future.await(MysqlTool.queryJsonObjectFromDb(MysqlClient.getGamePool(), sql, sqlParams));

                // 如果数据库不存在，判断是否需要新增数据
                if (!isEntityNotNull(jsonObject)) {
                    if (noExistInsert) {// 新增一条数据
                        try {
                            Model entity = (Model) cls.newInstance();
                            entity.putId(id);
                            jsonObject = entity.insert();
                        } catch (Exception e) {
                            logger.error(Tool.getException(e));
                        }
                    }
                }
                // 数据如果存在，则更新到redis中
                else {
                    // 更新字段名（下划线转驼峰）
                    JsonObject _jsonObject = updateJsonObjectKey(jsonObject);

                    int expireTime = getRedisExpireTime(cls);// 过期时间
                    long expireTimestamp = TimeUtils.getCurTime() + expireTime;// 到期时间戳

                    // json对象设置到期时间戳
                    if (expireTime > 0){
                        setJsonObjectExpireTime(_jsonObject, expireTimestamp);
                    }

                    // 更新到redis中
                    Boolean result1 = Future.await(RedisTools.setHashJsonObject( key, _jsonObject));

                    // 设置过期时间
                    setRedisExpireTime(key, expireTime);
                }
                return jsonObject;
            }
            // 数据没有初始化过，表示不存在
            else {
                // 判断是否需要新增
                JsonObject jsonObject = null;
                if (noExistInsert) {// 新增一条数据
                    try {
                        Model entity = (Model) cls.newInstance();
                        entity.putId(id);
                        jsonObject = entity.insert();
                    } catch (Exception e) {
                        logger.error(Tool.getException(e));
                    }
                }
                return jsonObject;
            }
        }
        // 无需入库也不用从数据库加载
        else {
            // 判断是否需要新增
            JsonObject jsonObject = null;
            if (noExistInsert) {// 新增一条数据
                try {
                    Model entity = (Model) cls.newInstance();
                    entity.putId(id);
                    jsonObject = entity.insert();
                } catch (Exception e) {
                    logger.error(Tool.getException(e));
                }
            }
            return jsonObject;
        }
    }

    @SuppressWarnings("rawtypes")
    private static JsonObject loadListFromDB(Class cls, String tableName, String listKeyField, String listKey, String listKeyId) {
        // 是否需要从数据库加载
        if (!EntityManager.isLoadDB()) {
            return null;
        }

        // 判断列表是否已经初始化，如果没有初始化则不用从数据库加载
        Future<Boolean> existsFuture = RedisTools.exists( getEntityInitKey(listKey));
        boolean listInit = Future.await(existsFuture);
        if (!listInit) {
            return null;
        }

        // 从数据库中重新加载
        String sql;
        String[] fields = listKeyField.split("\\.");
        if (listKeyField.equals(ALL_LIST_KEY)) {
            // 全表搜索
            sql = "SELECT * FROM " + tableName + ";";
        } else {
            // 根据列表字段搜索
            sql = "SELECT * FROM " + tableName + " where " + fields[0] + " = ?;";
        }
        JsonArray sqlParams = new JsonArray();
        if (!listKeyField.equals(ALL_LIST_KEY)) {
            sqlParams.add(listKeyId);
        }

        logger.info("loadListFromDB sql = {} sqlParams = {}", sql, sqlParams);

        Future<JsonArray> loadListFromDBFuture = MysqlTool.queryJsonArrayFromDb(MysqlClient.getGamePool(), sql, sqlParams);
        JsonArray array = Future.await(loadListFromDBFuture);

        // 列表数据保存到JsonObject中
        int expireTime = getRedisExpireTime(cls);// 过期时间
        long expireTimestamp = TimeUtils.getCurTime() + expireTime;// 到期时间戳
        JsonObject entityList = new JsonObject();
        boolean isOrderList = isOrderList(cls);
        List<String> orderList = new ArrayList<>();
        for (int i = 0, size = array.size(); i < size; i++) {
            JsonObject obj = array.getJsonObject(i);

            // 获取列表对象key（需要在转换字段名之前获取）
            String listItemKey = getListItemKey(fields, obj);

            // 新规范需要更新字段名（下划线转驼峰）
            updateJsonObjectKey(obj);

            // json对象设置到期时间戳
            if (expireTime > 0){
                setJsonObjectExpireTime(obj, expireTimestamp);
            }

            // 把对象更新到列表中
            entityList.put(listItemKey, obj);

            // 添加有序列表
            if (isOrderList){
                orderList.add(listItemKey);
            }
        }


        if (!entityList.isEmpty()){
            // 保存到redis
            Future<Boolean> setHashJsonObject = RedisTools.setHashJsonObject( listKey, entityList);
            Boolean result = Future.await(setHashJsonObject);

            // 设置过期时间
            setRedisExpireTime(listKey, expireTime);
        }

        // 添加有序列表
        if (isOrderList){
            Collections.sort(orderList);// 排序
            String orderListKey = EntityManager.getOrderListKey(listKey);
            Future.await(RedisTools.del(orderListKey));// 先删除再添加，防止有序列表数据重复
            Future.await(RedisTools.pushToList(orderListKey, orderList));

            // 设置过期时间
            setRedisExpireTime(orderListKey, expireTime);
        }

        return entityList;
    }

    /**
     * 列表数据如果过期从数据库加载
     *
     * @param cls     实体类
     * @param listKey 列表关键字值
     * @return 数据是否存在
     */
    @SuppressWarnings("rawtypes")
    public static boolean listExpireLoadFromDB(Class cls, String listKeyField, String listKey) {
        if (!EntityManager.isLoadDB()) {
            return true;
        }

        // 判断列表数据是否存在
        boolean exist = Future.await(RedisTools.exists( listKey));
        if (exist) {
            return true;
        }

        String listKeyId = null;
        String[] listKeys = listKey.split("\\.");
        String entityKey = listKeys[0];
        if (listKeys.length > 1) {
            listKeyId = listKeys[1];
        }
        String tableName = isNewCode() ? Tool.upperCaseToUnderline(entityKey) : entityKey;

        // 从数据库读取列表数据
        JsonObject list = loadListFromDB(cls, tableName, listKeyField, listKey, listKeyId);
        return list != null;
    }

    /***
     * 等待所有的事务都完成以后再回调
     * @param futures
     * @param onComplete
     */
    public static void waitAll(List<Future<?>> futures, Handler<AsyncResult<JsonArray>> onComplete) {
        Future.all(futures).onComplete(handler -> {
            JsonArray result = new JsonArray();
            for (Future<?> fut : futures) {
                JsonObject obj = (JsonObject) fut.result();
                if (obj != null) {
                    result.add(obj);
                }
            }
            onComplete.handle(Future.succeededFuture(result));

        });
    }

    /**
     * 删除所有实体类数据（包括数据库和redis）
     *
     * @param cls 实体类
     */
    public static void delEntity(Class cls) {
        delEntity(cls, null);// listKeyId为空表示删除所有数据
    }

    /**
     * 删除某个字段的实体类数据（包括数据库和redis）
     *
     * @param cls       实体类
     * @param listKeyId 删除某个条件字段的数据
     */
    public static void delEntity(Class cls, long listKeyId) {
        delEntity(cls, String.valueOf(listKeyId));
    }

    /**
     * 删除某个字段的实体类数据（包括数据库和redis）
     *
     * @param cls       实体类
     * @param listKeyId 删除某个条件字段的数据
     */
    public static void delEntity(Class cls, String listKeyId) {
        String entityKey = isNewCode() ? cls.getSimpleName() : cls.getSimpleName().toLowerCase();// 新规范类名，旧规范表名
        String tableName = isNewCode() ? Tool.upperCaseToUnderline(entityKey) : entityKey;
        String listKeyField = getListKeyField(cls);
        String[] fields = listKeyField.split("\\.");
        String listKey = getListKey(entityKey, listKeyField, listKeyId);
        String listInitKey = getEntityInitKey(listKey);
        boolean isOrderList = isOrderList(cls);
        String orderListKey = getOrderListKey(listKey);

        Promise<Void> future = Promise.promise();

        // 删除有列表关键字的数据，或者是全表列表数据
        if (!Tool.isEmpty(listKeyId) || listKeyField.equals(ALL_LIST_KEY)) {
            // 删除列表init数据
            RedisTools.del( listInitKey, h1 -> {
                if (h1.succeeded()) {
                    // 删除列表数据
                    RedisTools.del( listKey, h2 -> {
                        if (h2.succeeded()) {
                            // 删除有序列表
                            if (isOrderList){
                                RedisTools.del( orderListKey, h3 -> {
                                    if (h3.succeeded()) {
                                        future.complete();
                                    } else {
                                        future.fail(h3.cause());
                                    }
                                });
                            } else{
                                future.complete();
                            }
                        } else {
                            future.fail(h2.cause());
                        }
                    });
                } else {
                    future.fail(h1.cause());
                }
            });
        }
        // 删除单条数据表的全部数据，或者是删除列表数据表全部数据
        else {

            // 删除单条数据表的全部数据
            if (Tool.isEmpty(listKeyField)) {
                String sql1 = "select id from " + tableName + ";";
                MysqlTool.queryJsonArrayFromDb(MysqlClient.getGamePool(), sql1, new JsonArray(), resGetIds -> {
                    if (resGetIds.succeeded()) {
                        JsonArray idArray = resGetIds.result();
                        List<String> delKeys = new ArrayList<>();
                        List<String> delInitKeys = new ArrayList<>();
                        for (int i = 0; i < idArray.size(); i++) {
                            JsonObject objId = idArray.getJsonObject(i);
                            String key = getKey(entityKey, objId.getLong("id"));
                            delKeys.add(key);
                            delInitKeys.add(EntityManager.getEntityInitKey(key));
                        }
                        // 删除init key
                        RedisTools.delMany( delInitKeys, h2 -> {
                            if (h2.succeeded()) {
                                // 删除实体数据
                                RedisTools.delMany( delKeys, h3 -> {
                                    if (h3.succeeded()) {
                                        future.complete();
                                    } else {
                                        future.fail(h3.cause());
                                    }
                                });
                            } else {
                                future.fail(h2.cause());
                            }
                        });
                    } else {
                        future.fail(resGetIds.cause());
                    }
                });
            }

            // 删除列表数据表全部数据
            else {
                String sql1 = "select DISTINCT " + fields[0] + " from " + tableName + ";";
                MysqlTool.queryJsonArrayFromDb(MysqlClient.getGamePool(), sql1, new JsonArray(), resGetListId -> {
                    JsonArray listIDArray = resGetListId.result();
                    List<String> delListKeys = new ArrayList<>();
                    List<String> delListInitKeys = new ArrayList<>();
                    List<String> delOrderListKeys = new ArrayList<>();
                    for (int i = 0; i < listIDArray.size(); i++) {
                        JsonObject objId = listIDArray.getJsonObject(i);
                        String listKey1 = getKey(entityKey, objId.getValue(fields[0]));
                        delListKeys.add(listKey1);
                        delListInitKeys.add(getEntityInitKey(listKey1));
                        delOrderListKeys.add(getOrderListKey(listKey1));
                    }

                    // 删除initkey
                    RedisTools.delMany( delListInitKeys, h3 -> {
                        if (h3.succeeded()) {
                            // 删除列表数据
                            RedisTools.delMany( delListKeys, h4 -> {
                                if (h4.succeeded()) {
                                    // 删除有序列表
                                    if (isOrderList){
                                        RedisTools.delMany( delOrderListKeys, h5 -> {
                                            if (h5.succeeded()) {
                                                future.complete();
                                            } else {
                                                future.fail(h5.cause());
                                            }
                                        });
                                    } else{
                                        future.complete();
                                    }
                                } else {
                                    future.fail(h4.cause());
                                }
                            });
                        } else {
                            future.fail(h3.cause());
                        }
                    });
                });
            }
        }

        // 删除数据库数据
        String sql;
        if (!Tool.isEmpty(listKeyId)) {
            sql = "delete from " + tableName + " where " + fields[0] + " = ?;";
        } else {
            sql = "delete from " + tableName + ";";
        }
        JsonArray sqlParams = new JsonArray();
        if (!Tool.isEmpty(listKeyId)) {
            sqlParams.add(listKeyId);
        }
        future.future().onComplete(resDelDB -> {
            if (resDelDB.succeeded()) {
                delToDBQueue(tableName, sql, sqlParams);
            } else {
                logger.error(Tool.getException(resDelDB.cause()));
            }
        });
    }

    /**
     * 删除单条记录（不需要执行reset方法）
     * @param cls 删除的类型
     * @param values 删除关键字段（就是获取对象的关键字段）
     */
    public static void delOneEntity(Class cls, Object... values) {
        Model model = loadEntity(cls, false, false, values);
        if (model != null) {
            model.delete();
        }
    }

    /**
     * 同步删除某个字段的实体类数据（包括数据库和redis）
     *
     * @param cls 实体类
     */
    public static void delEntitySync(Class cls) {
        delEntitySync(cls, null);
    }

    /**
     * 同步删除某个字段的实体类数据（包括数据库和redis）
     *
     * @param cls       实体类
     * @param listKeyId 删除某个条件字段的数据
     */
    public static void delEntitySync(Class cls, long listKeyId) {
        delEntitySync(cls, String.valueOf(listKeyId));
    }

    /**
     * 同步删除某个字段的实体类数据（包括数据库和redis）
     *
     * @param cls       实体类
     * @param listKeyId 删除某个条件字段的数据
     */
    public static void delEntitySync(Class cls, String listKeyId) {
        String entityKey = isNewCode() ? cls.getSimpleName() : cls.getSimpleName().toLowerCase();// 新规范类名，旧规范表名
        String tableName = isNewCode() ? Tool.upperCaseToUnderline(entityKey) : entityKey;
        String listKeyField = getListKeyField(cls);
        String[] fields = listKeyField.split("\\.");
        String listKey = getListKey(entityKey, listKeyField, listKeyId);
        String listInitKey = getEntityInitKey(listKey);
        boolean isOrderList = isOrderList(cls);
        String orderListKey = getOrderListKey(listKey);

        // 删除有列表关键字的数据，或者是全表列表数据
        if (!Tool.isEmpty(listKeyId) || listKeyField.equals(ALL_LIST_KEY)) {
            // 删除列表init数据
            boolean delInit = Future.await(RedisTools.del( listInitKey));

            // 删除列表数据
            boolean delList = Future.await(RedisTools.del( listKey));

            // 删除有序列表
            if (isOrderList) {
                boolean delOrderList = Future.await(RedisTools.del( orderListKey));
            }
        }

        // 删除单条数据表的全部数据，或者是删除列表数据表全部数据
        else {
            // 删除单条数据表的全部数据
            if (Tool.isEmpty(listKeyField)) {
                String sql1 = "select id from " + tableName + ";";
                JsonArray idArray = Future.await(MysqlTool.queryJsonArrayFromDb(MysqlClient.getGamePool(), sql1, new JsonArray()));
                List<String> delKeys = new ArrayList<>();
                List<String> delInitKeys = new ArrayList<>();
                for (int i = 0; i < idArray.size(); i++) {
                    JsonObject objId = idArray.getJsonObject(i);
                    String key = getKey(entityKey, objId.getLong("id"));
                    delKeys.add(key);
                    delInitKeys.add(EntityManager.getEntityInitKey(key));
                }

                // 删除列表init数据
                long delInitNum = Future.await(RedisTools.delMany( delInitKeys));

                // 删除列表数据
                long delListNum = Future.await(RedisTools.delMany( delKeys));
            }
            // 删除列表数据表全部数据
            else {
                String sql1 = "select DISTINCT " + fields[0] + " from " + tableName + ";";
                JsonArray listIDArray = Future.await(MysqlTool.queryJsonArrayFromDb(MysqlClient.getGamePool(), sql1, new JsonArray()));
                List<String> delListKeys = new ArrayList<>();
                List<String> delListInitKeys = new ArrayList<>();
                List<String> delOrderListKeys = new ArrayList<>();
                for (int i = 0; i < listIDArray.size(); i++) {
                    JsonObject objId = listIDArray.getJsonObject(i);
                    String listKey1 = getKey(entityKey, objId.getValue(fields[0]));
                    delListKeys.add(listKey1);
                    delListInitKeys.add(getEntityInitKey(listKey1));
                    delOrderListKeys.add(getOrderListKey(listKey1));
                }

                // 删除列表init数据
                long delInitNum = Future.await(RedisTools.delMany( delListInitKeys));

                // 删除列表数据
                long delListNum = Future.await(RedisTools.delMany( delListKeys));

                // 删除有序列表
                if (isOrderList) {
                    long delOrderListNum = Future.await(RedisTools.delMany( delOrderListKeys));
                }
            }
        }

        // 删除数据库数据
        String sql;
        if (!Tool.isEmpty(listKeyId)) {
            sql = "delete from " + tableName + " where " + fields[0] + " = ?;";
        } else {
            sql = "delete from " + tableName + ";";
        }
        JsonArray sqlParams = new JsonArray();
        if (!Tool.isEmpty(listKeyId)) {
            sqlParams.add(listKeyId);
        }
        Object await = Future.await(MysqlTool.updateToDb(MysqlClient.getGamePool(), sql, sqlParams));
    }

    /**
     * 更新所有实体类数据
     *
     * @param cls        实体类
     * @param jsonObject 更新内容(key需要传驼峰格式)
     */
    public static void updateEntity(Class cls, JsonObject jsonObject) {
        updateEntity(cls, null, jsonObject);
    }

    /**
     * 更新实体类数据
     *
     * @param cls        实体类
     * @param listKeyId  更新某个条件字段的数据
     * @param jsonObject 更新内容(key需要传驼峰格式)
     */
    public static void updateEntity(Class cls, long listKeyId, JsonObject jsonObject) {
        updateEntity(cls, String.valueOf(listKeyId), jsonObject);
    }

    /**
     * 更新实体类数据
     *
     * @param cls       实体类
     * @param listKeyId 更新某个条件字段的数据
     * @param updateObj 更新内容(key需要传驼峰格式)
     */
    public static void updateEntity(Class cls, String listKeyId, JsonObject updateObj) {
        String entityKey = isNewCode() ? cls.getSimpleName() : cls.getSimpleName().toLowerCase();// 新规范类名，旧规范表名
        String tableName = isNewCode() ? Tool.upperCaseToUnderline(entityKey) : entityKey;
        if (updateObj.size() == 0) {
            logger.error("updateEntity tableName = " + tableName + " value = " + listKeyId + " jsonObject is empty !!!");
        }
        String listKeyField = getListKeyField(cls);
        String[] fields = listKeyField.split("\\.");
        String listKey = getListKey(entityKey, listKeyField, listKeyId);

        // 创建sql语句
        String sql = "";
        for (Iterator<Entry<String, Object>> iter = updateObj.iterator(); iter.hasNext(); ) {
            Entry<String, Object> entry = iter.next();
            String field = isNewCode() ? Tool.upperCaseToUnderline(entry.getKey()) : entry.getKey();// 驼峰转下划线
            field = "`" + field + "`";// 字段名转义，避免关键字冲突
            if (sql.isEmpty()) {
                sql += field + " = " + entry.getValue();
            } else {
                sql += "," + field + " = " + entry.getValue();
            }
        }
        sql = "update " + tableName + " set " + sql;
        if (!Tool.isEmpty(listKeyId)) {
            sql += " where " + fields[0] + " = ?;";
        } else {
            sql += ";";
        }
        JsonArray sqlParams = new JsonArray();
        if (!Tool.isEmpty(listKeyId)) {
            sqlParams.add(listKeyId);
        }

        // 更新数据库
        MysqlTool.updateToDb(MysqlClient.getGamePool(), sql, sqlParams, h -> {
            if (h.succeeded()) {
                // 更新有列表关键字的数据，或者是全表列表数据
                if (!Tool.isEmpty(listKeyId) || listKeyField.equals(ALL_LIST_KEY)) {
                    RedisTools.getHashJsonObject( listKey, h1 -> {
                        if (h1.succeeded()) {
                            JsonObject list = h1.result();
                            logger.info("updateEntity table = " + tableName + " entity(" + listKey + ") num = " + list.size());
                            for (Iterator<Entry<String, Object>> iter = list.iterator(); iter.hasNext(); ) {
                                Entry<String, Object> entry = iter.next();
                                JsonObject item = new JsonObject((String) entry.getValue());
                                item.mergeIn(updateObj);
                                list.put(entry.getKey(), item);
                            }
                            RedisTools.setHashJsonObject( listKey, list);
                        } else {
                            logger.error(Tool.getException(h1.cause()));
                        }
                    });
                }
                // 更新单条数据表的全部数据，或者是更新列表数据表全部数据
                else {
                    // 删除单条数据表的全部数据
                    if (Tool.isEmpty(listKeyField)) {
                        String sql1 = "select id from " + tableName + ";";
                        MysqlTool.queryJsonArrayFromDb(MysqlClient.getGamePool(), sql1, new JsonArray(), resGetIds -> {
                            if (resGetIds.succeeded()) {
                                JsonArray idArray = resGetIds.result();
                                logger.info("updateEntity table = " + tableName + " num = " + idArray.size());
                                for (int i = 0; i < idArray.size(); i++) {
                                    JsonObject objId = idArray.getJsonObject(i);
                                    String key = getKey(entityKey, objId.getLong("id"));
                                    RedisTools.setHashJsonObject( key, updateObj);
                                }
                            } else {
                                logger.error(Tool.getException(resGetIds.cause()));
                            }
                        });
                    }
                    // 更新列表数据表全部数据
                    else {
                        String sql1 = "select DISTINCT " + fields[0] + " from " + tableName + ";";
                        MysqlTool.queryJsonArrayFromDb(MysqlClient.getGamePool(), sql1, new JsonArray(), resGetListId -> {
                            JsonArray listIDArray = resGetListId.result();
                            for (int i = 0; i < listIDArray.size(); i++) {
                                JsonObject objId = listIDArray.getJsonObject(i);
                                String listKey1 = getKey(entityKey, objId.getValue(fields[0]));
                                RedisTools.getHashJsonObject( listKey1, h1 -> {
                                    if (h1.succeeded()) {
                                        JsonObject list = h1.result();
                                        logger.info("updateEntity table = " + tableName + " entity(" + listKey1 + ") num = " + list.size());
                                        for (Iterator<Entry<String, Object>> iter = list.iterator(); iter.hasNext(); ) {
                                            Entry<String, Object> entry = iter.next();
                                            JsonObject item = new JsonObject((String) entry.getValue());
                                            item.mergeIn(updateObj);
                                            list.put(entry.getKey(), item);
                                        }
                                        RedisTools.setHashJsonObject( listKey1, list);
                                    } else {
                                        logger.error(Tool.getException(h1.cause()));
                                    }
                                });
                            }
                        });
                    }
                }
            } else {
                logger.error(Tool.getException(h.cause()));
            }
        });
    }

    /**
     * 同步更新实体类数据
     *
     * @param cls       实体类
     * @param updateObj 更新内容(key需要传驼峰格式)
     */
    public static void updateEntitySync(Class cls, JsonObject updateObj) {
        updateEntitySync(cls, null, updateObj);
    }

    /**
     * 同步更新实体类数据
     *
     * @param cls       实体类
     * @param listKeyId 更新某个条件字段的数据
     * @param updateObj 更新内容(key需要传驼峰格式)
     */
    public static void updateEntitySync(Class cls, long listKeyId, JsonObject updateObj) {
        updateEntitySync(cls, String.valueOf(listKeyId), updateObj);
    }

    /**
     * 同步更新实体类数据
     *
     * @param cls       实体类
     * @param listKeyId 更新某个条件字段的数据
     * @param updateObj 更新内容(key需要传驼峰格式)
     */
    public static void updateEntitySync(Class cls, String listKeyId, JsonObject updateObj) {
        String entityKey = isNewCode() ? cls.getSimpleName() : cls.getSimpleName().toLowerCase();// 新规范类名，旧规范表名
        String tableName = isNewCode() ? Tool.upperCaseToUnderline(entityKey) : entityKey;
        if (updateObj.size() == 0) {
            logger.error("updateEntity tableName = " + tableName + " value = " + listKeyId + " jsonObject is empty !!!");
        }
        String listKeyField = getListKeyField(cls);
        String[] fields = listKeyField.split("\\.");
        String listKey = getListKey(entityKey, listKeyField, listKeyId);

        // 创建sql语句
        String sql = "";
        for (Iterator<Entry<String, Object>> iter = updateObj.iterator(); iter.hasNext(); ) {
            Entry<String, Object> entry = iter.next();
            String field = isNewCode() ? Tool.upperCaseToUnderline(entry.getKey()) : entry.getKey();// 驼峰转下划线
            field = "`" + field + "`";// 字段名转义，避免关键字冲突
            if (sql.isEmpty()) {
                sql += field + " = " + entry.getValue();
            } else {
                sql += "," + field + " = " + entry.getValue();
            }
        }
        sql = "update " + tableName + " set " + sql;
        if (!Tool.isEmpty(listKeyId)) {
            sql += " where " + fields[0] + " = ?;";
        } else {
            sql += ";";
        }
        JsonArray sqlParams = new JsonArray();
        if (!Tool.isEmpty(listKeyId)) {
            sqlParams.add(listKeyId);
        }

        // 更新数据库
        String _sql = sql;
        Object awaitObj = Future.await(MysqlTool.updateToDb(MysqlClient.getGamePool(), _sql, sqlParams));

        // 更新有列表关键字的数据，或者是全表列表数据
        if (!Tool.isEmpty(listKeyId) || listKeyField.equals(ALL_LIST_KEY)) {
            JsonObject list = Future.await(RedisTools.getHashJsonObject( listKey));
            logger.info("updateEntity table = " + tableName + " entity(" + listKey + ") num = " + list.size());
            for (Iterator<Entry<String, Object>> iter = list.iterator(); iter.hasNext(); ) {
                Entry<String, Object> entry = iter.next();
                JsonObject item = new JsonObject((String) entry.getValue());
                item.mergeIn(updateObj);
                list.put(entry.getKey(), item);
            }
            boolean updateResult = Future.await(RedisTools.setHashJsonObject( listKey, list));
        }
        // 更新单条数据表的全部数据，或者是更新列表数据表全部数据
        else {
            // 更新单条数据表的全部数据
            if (Tool.isEmpty(listKeyField)) {
                String sql1 = "select id from " + tableName + ";";
                JsonArray idArray = Future.await(MysqlTool.queryJsonArrayFromDb(MysqlClient.getGamePool(), sql1, new JsonArray()));
                logger.info("updateEntity table = " + tableName + " num = " + idArray.size());
                for (int i = 0; i < idArray.size(); i++) {
                    JsonObject objId = idArray.getJsonObject(i);
                    String key = getKey(entityKey, objId.getLong("id"));
                    boolean updateResult = Future.await(RedisTools.setHashJsonObject( key, updateObj));
                }
            }
            // 更新列表数据表全部数据
            else {
                String sql1 = "select DISTINCT " + fields[0] + " from " + tableName + ";";
                JsonArray listIDArray = Future.await(MysqlTool.queryJsonArrayFromDb(MysqlClient.getGamePool(), sql1, new JsonArray()));
                for (int i = 0; i < listIDArray.size(); i++) {
                    JsonObject objId = listIDArray.getJsonObject(i);
                    String listKey1 = getKey(entityKey, objId.getValue(fields[0]));
                    JsonObject list = Future.await(RedisTools.getHashJsonObject( listKey1));
                    logger.info("updateEntity table = " + tableName + " entity(" + listKey1 + ") num = " + list.size());
                    for (Iterator<Entry<String, Object>> iter = list.iterator(); iter.hasNext(); ) {
                        Entry<String, Object> entry = iter.next();
                        JsonObject item = new JsonObject((String) entry.getValue());
                        item.mergeIn(updateObj);
                        list.put(entry.getKey(), item);
                    }
                    boolean updateResult = Future.await(RedisTools.setHashJsonObject( listKey1, list));
                }
            }
        }
    }

    public static long incrTableId(String key) {
        long initId = BaseServerParam.TABLE_INIT_ID;
        boolean init = Future.await(RedisTools.hsetnx(RedisTools.getTableidKey(), key, String.valueOf(initId)));
        if (init) {
            logger.info("### table = " + key + " init id = " + initId);
            return initId;
        } else {
            long r = Future.await(RedisTools.incrTableId(key));
            return r;
        }
    }

    // 删除命令加入到db队列
    public static void delToDBQueue(String tableName, String sql, JsonArray sqlParams) {
        JsonObject updateDb = new JsonObject();
        updateDb.put("status", BaseModel.DELETE);// 0需要判断是否存在数据库，1新增，2修改，3删除
        updateDb.put("sql", sql);
        updateDb.put("params", sqlParams.toString());
//        if (ServerConfig.isReviewServer()) {// 评审服用redis队列写入数据库
//            RedisTools.pushToList(EntityManager.getUpdateDbKey(), updateDb.toString());
//        } else {
            DbManager.pushDBQueue(tableName, null, updateDb);
//        }
    }

    /**
     * 获取redis实体类过期时间
     *
     * @param cls 实体类
     */
    public static int getRedisExpireTime(Class cls) {
        if (BaseServerParam.REDIS_EXPIRE_TIME == 0) {
            return 0;
        }
        int expireTime;// redis过期时间（秒）
        try {
            Integer REDIS_EXPIRE_TIME = (Integer) cls.getField("REDIS_EXPIRE_TIME").get(cls);// 实体类配置的redis过期时间
            expireTime = REDIS_EXPIRE_TIME.intValue();
        } catch (Exception e) {
            expireTime = 0;
        }
        if (expireTime == 0) {
            expireTime = BaseServerParam.REDIS_EXPIRE_TIME;
        }
        return expireTime;
    }

    /**
     * 获取对象里的过期时间（手动赋值是int类型，从redis取出来是string类型，所以需要区分）
     */
    public static long getJsonObjectExpireTime(JsonObject jsonObject) {
        if (jsonObject == null || !jsonObject.containsKey(BaseModel.REDIS_EXPIRE_TIME)){
            return 0;
        }
        Object value = jsonObject.getValue(BaseModel.REDIS_EXPIRE_TIME);
        if (value instanceof CharSequence) {
            CharSequence cs = (CharSequence)value;
            return cs == null ? 0 : Long.parseLong(cs.toString());
        } else if (value instanceof Number) {
            Number number = (Number)value;
            if (number == null) {
                return 0;
            } else if (number instanceof Long) {
                return (Long)number;  // Avoids unnecessary unbox/box
            } else {
                return number.longValue();
            }
        } else{
            return 0;
        }
    }

    /**
     * 设置redis实体类过期时间
     *
     * @param key redis key
     * @param cls 实体类
     */
    public static int setRedisExpireTime(String key, Class cls) {
        int expireTime = getRedisExpireTime(cls);// redis过期时间（秒）
        if (expireTime > 0) {
            RedisTools.expire(key, expireTime);
        }
        return expireTime;
    }

    /**
     * 设置redis实体类过期时间
     *
     * @param key        redis key
     * @param expireTime 过期时间
     */
    public static int setRedisExpireTime(String key, int expireTime) {
        if (expireTime > 0) {
            RedisTools.expire(key, expireTime);
        }
        return expireTime;
    }

    /**
     * 获取更新数据库类型
     */
    public static int getUpdateDbType(Class cls) {
        int UPDATE_DB_TYPE;
        try {
            UPDATE_DB_TYPE = (Integer) cls.getField("UPDATE_DB_TYPE").get(cls);
        } catch (Exception e) {
            UPDATE_DB_TYPE = BaseModel.UPDATE_DB_TYPE_QUEUE;
        }
        return UPDATE_DB_TYPE;
    }

    /**
     * 设置读取对象的过期时间
     */
    public static void setEntityExpireTime(String key, Class cls, JsonObject jsonObject) {
        if (BaseServerParam.REDIS_EXPIRE_TIME == 0) {
            return;
        }
        long curTime = TimeUtils.getCurTime();
        long redisExpireTime = getJsonObjectExpireTime(jsonObject);
        if (redisExpireTime - curTime < BaseServerParam.REDIS_EXPIRE_UPDATE_TIME) {
            int expireTime = setRedisExpireTime(key, cls);
            if (expireTime > 0){
                jsonObject.put(BaseModel.REDIS_EXPIRE_TIME, curTime + expireTime);
                RedisTools.setHashJsonObject( key, new JsonObject().put(BaseModel.REDIS_EXPIRE_TIME, curTime + expireTime));
            }
        }
    }

    /**
     * JsonObject对象设置过期时间
     *
     * @param jsonObject      json对象
     * @param redisExpireTime 到期时间戳
     */
    private static void setJsonObjectExpireTime(JsonObject jsonObject, long redisExpireTime) {
        jsonObject.put(BaseModel.REDIS_EXPIRE_TIME, redisExpireTime);
    }

    /**
     * 把jsonobject的key下划线转大写字母
     *
     * @param jsonObject 需要修改的jsonObject
     */
    public static JsonObject updateJsonObjectKey(JsonObject jsonObject) {
        if (!isNewCode()) {
            return jsonObject;
        }
        JsonObject changeJsonObject = new JsonObject();
        for (Iterator<Entry<String, Object>> iter = jsonObject.iterator(); iter.hasNext(); ) {
            Entry<String, Object> entry = iter.next();
            String key = entry.getKey();
            if (key.contains("_")) {
                iter.remove();
                changeJsonObject.put(Tool.underlineToUpperCase(key), entry.getValue());
            }
        }
        if (!changeJsonObject.isEmpty()) {
            jsonObject.mergeIn(changeJsonObject);
        }
        return jsonObject;
    }

    /**
     * 获取实体类列表关键字段
     *
     * @param cls 实体类
     * @return 列表关键字段
     */
    public static String getListKeyField(Class cls) {
        String LISTKEY;
        try {
            LISTKEY = String.valueOf(cls.getField("LISTKEY").get(cls));
        } catch (Exception e) {
            logger.error("get LISTKEY error class name = {}", cls.getSimpleName());
            return null;
        }
        return LISTKEY;
    }

    /**
     * 获取实体类列表关键字段数组
     *
     * @param cls 实体类
     * @return 列表关键字段数组
     */
    public static String[] getListKeyFields(Class cls) {
        String LISTKEY = getListKeyField(cls);
        if (LISTKEY == null) {
            return null;
        }
        String[] fields = LISTKEY.split("\\.");
        return fields;
    }

    /**
     * 实体类是否包含排序列表
     */
    public static boolean isOrderList(Class cls) {
        boolean isOrderList;
        try {
            isOrderList = (boolean)cls.getField("ORDER_LIST").get(cls);
        } catch (Exception e) {
            logger.error("get ORDER_LIST error class name = {}", cls.getSimpleName());
            return false;
        }
        return isOrderList;
    }

    /**
     * 获取列表对象的key
     *
     * @param listKeyFields 列表关键字段数组
     * @param item          列表单个对象信息
     * @return 列表对象的key
     */
    public static String getListItemKey(String[] listKeyFields, JsonObject item) {
        if (listKeyFields.length > 1) {
            // 如果列表有多个字段，则排除第一个列表关键字，其他字段组合成对象key（例如userid.itemid，那么只需要用itemid作为对象的key）
            Object[] values = new Object[listKeyFields.length - 1];
            for (int i = 1; i < listKeyFields.length; i++) {
                values[i - 1] = item.getValue(listKeyFields[i]).toString();
            }
            return getValue(values);
        } else {
            // 如果列表没有字段或者只有1个字段，那么用id作为对象key
            return item.getValue("id").toString();
        }
    }

    /**
     * 获取列表对象的key
     *
     * @param values 获取实体对象传参
     * @return 列表对象的key
     */
    public static String getListItemKey(Object... values) {
        if (values.length <= 2) {
            // 2个（包含）字段以下都是取最后一个值作为key
            return String.valueOf(values[values.length - 1]);
        } else {
            String result = "";
            for (int i = 1; i < values.length; i++) {
                if (Tool.isEmpty(result)) {
                    result = String.valueOf(values[i]);
                } else {
                    result += "." + values[i];
                }
            }
            return result;
        }
    }

    /**
     * 判断实体对象是否为空
     *
     * @param entity
     */
    public static boolean isEntityNotNull(JsonObject entity) {
        return entity != null && entity.containsKey("id");
    }

    /**
     * 获取实体类字段拼接字符串（实体类字段拼接不能用点号，否则解析会报错，所以这里是用下划线）
     * @param values 拼接列表
     * @return 拼接字符串
     */
    public static String getFieldJoinString(Object... values) {
        String value = "";
        for (int i = 0; i < values.length; i++) {
            if (value.equals("")) {
                value = String.valueOf(values[i]);
            } else {
                value += "_" + values[i];
            }
        }
        return value;
    }

}
